#include <iostream>
#include "basic/basic.h"
#include "gc/gc.h"
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>

///////////////////////////
class Base{
public:
	Base():val_(0){
		std::cout << "Deliver::Base" << std::endl;
	}
	virtual ~Base(){
		std::cout << "Deliver::~Base" << std::endl;
	}

	virtual void print(){
		std::cout << "Base::print" << std::endl;
	};
private:
	int val_;
};
class Deliver : public Base{
public:
	Deliver(){
		std::cout << "Deliver::Deliver" << std::endl;
	}
	virtual ~Deliver(){
		std::cout << "Deliver::~Deliver" << std::endl;
	}

	virtual void print(){
		std::cout << "Deliver::print" << std::endl;
	};
};
class DeliverEx : public Base, public eyas::gc::enable_memory_pool<DeliverEx>{
public:
	DeliverEx(){
		std::cout << "Deliver::Deliver" << std::endl;
	}
	virtual ~DeliverEx(){
		std::cout << "Deliver::~Deliver" << std::endl;
	}

	virtual void print(){
		std::cout << "Deliver::print" << std::endl;
	};
};

int main() {
	typedef boost::shared_ptr<Base> BasePtr;
	typedef boost::shared_ptr<Deliver> DeliverPtr;
	clock_t clk = 0;
	clock_t clk2 = 0;
	void* mem = 0;

	eyas::gc::init();
	do{
		clk = ::clock();
		for(int i=0; i<500000; i++){
			DeliverPtr dptr = eyas::gc::create_new<Deliver>();
			DeliverPtr dptr2 = eyas::gc::create_new<Deliver>();
			DeliverPtr dptr3 = eyas::gc::create_new<Deliver>();

			dptr->print();
			dptr2->print();
			dptr3->print();
		}
		clk2 = ::clock();
		std::cout << "eyas::gc::create_new shared_ptr waste time: " << (clk2-clk) << std::endl;
		//getchar();
		clk = ::clock();
		for(int i=0; i<500000; i++){
			mem = eyas::gc::static_memory_pool<sizeof(Deliver)>::instance()->allocate();
			DeliverPtr dptr(new (mem) Deliver(), eyas::gc::deleter_t<Deliver>());
			mem = eyas::gc::static_memory_pool<sizeof(Deliver)>::instance()->allocate();
			DeliverPtr dptr2(new (mem) Deliver(), eyas::gc::deleter_t<Deliver>());
			mem = eyas::gc::static_memory_pool<sizeof(Deliver)>::instance()->allocate();
			DeliverPtr dptr3(new (mem) Deliver(), eyas::gc::deleter_t<Deliver>());

			
			dptr->print();
			dptr2->print();
			dptr3->print();
		}
		clk2 = ::clock();
		std::cout << "eyas::gc::deleter_t shared_ptr waste time: " << (clk2-clk) << std::endl;
		
		//getchar();
		clk = ::clock();
		for(int i=0; i<500000; i++){
			DeliverPtr dptr = boost::make_shared<Deliver>();
			DeliverPtr dptr2 = boost::make_shared<Deliver>();
			DeliverPtr dptr3 = boost::make_shared<Deliver>();

			
			dptr->print();
			dptr2->print();
			dptr3->print();
		}
		clk2 = ::clock();
		std::cout << "boost::make_shared shared_ptr waste time: " << (clk2-clk) << std::endl;
		//getchar();

		
		clk = ::clock();
		for(int i=0; i<500000; i++){
			// 可能有内存泄漏风险
			mem = eyas::gc::static_memory_pool<sizeof(DeliverEx)>::instance()->allocate();
			DeliverEx* dptr = new (mem) DeliverEx();
			mem = eyas::gc::static_memory_pool<sizeof(DeliverEx)>::instance()->allocate();
			DeliverEx* dptr2 = new (mem) DeliverEx();
			mem = eyas::gc::static_memory_pool<sizeof(DeliverEx)>::instance()->allocate();
			DeliverEx* dptr3 = new (mem) DeliverEx();

			dptr->print();
			dptr2->print();
			dptr3->print();

			dptr->~DeliverEx();
			dptr2->~DeliverEx();
			dptr3->~DeliverEx();
			eyas::gc::static_memory_pool<sizeof(DeliverEx)>::instance()->deallocate(dptr);
			eyas::gc::static_memory_pool<sizeof(DeliverEx)>::instance()->deallocate(dptr2);
			eyas::gc::static_memory_pool<sizeof(DeliverEx)>::instance()->deallocate(dptr3);
		}
		clk2 = ::clock();
		std::cout << "eyas::gc::static_memory_pool raw waste time: " << (clk2-clk) << std::endl;
		clk = ::clock();
		for(int i=0; i<500000; i++){
			DeliverEx* dptr = new DeliverEx();
			DeliverEx* dptr2 = new DeliverEx();
			DeliverEx* dptr3 = new DeliverEx();

			dptr->print();
			dptr2->print();
			dptr3->print();


			delete dptr;
			delete dptr2;
			delete dptr3;
		}
		clk2 = ::clock();
		std::cout << "eyas::gc::static_memory_pool raw new waste time: " << (clk2-clk) << std::endl;
		clk = ::clock();
		for(int i=0; i<500000; i++){
			Deliver* dptr = new Deliver();
			Deliver* dptr2 = new Deliver();
			Deliver* dptr3 = new Deliver();

			dptr->print();
			dptr2->print();
			dptr3->print();


			delete dptr;
			delete dptr2;
			delete dptr3;
		}
		clk2 = ::clock();
		std::cout << "raw new waste time: " << (clk2-clk) << std::endl;


		{
			DeliverPtr dptr = eyas::gc::create_new<Deliver>();
			DeliverPtr dptr2 = eyas::gc::create_new<Deliver>();
			DeliverPtr dptr3 = eyas::gc::create_new<Deliver>();
			clk = ::clock();
			for(int i=0; i<500000; i++){
				dptr->print();
				dptr2->print();
				dptr3->print();
			}
			clk2 = ::clock();
		}
		std::cout << "shared_ptr call waste time: " << (clk2-clk) << std::endl;
		{
			Deliver* dptr = new Deliver();
			Deliver* dptr2 = new Deliver();
			Deliver* dptr3 = new Deliver();
			clk = ::clock();
			for(int i=0; i<500000; i++){
				dptr->print();
				dptr2->print();
				dptr3->print();
			}
			clk2 = ::clock();
			delete dptr;
			delete dptr2;
			delete dptr3;
		}
		std::cout << "raw call waste time: " << (clk2-clk) << std::endl;
		getchar();
	}while(false);
	std::cout << "Enter exit the test." << std::endl;
	getchar();
	return 0;
}
